<template>
  <div>
    <!-- -->

    <div class="mainboxgj">
      <div class="boxs">
        <!-- <canvas id="myCanvas" width="300" height="500"></canvas> -->
        <div class="boxsitem"></div>
        <div class="boxsitems">横断面</div>
        <div class="boxsitem"></div>
        <div class="boxsitems">矢断面</div>
        <div class="boxsitem"></div>
        <div class="boxsitems">冠断面</div>
      </div>
      <div class="box">
        <canvas id="myCanvas" width="1300" height="500"></canvas>
      </div>
      <div class="bocd">
        <div>
          <a-card :style="{ width: '360px' }" title="功能菜单">
            <template #extra>
              <a-link></a-link>
            </template>
            <a-button type="primary" @click="zoomIn">放大</a-button>
            <a-button type="primary" @click="zoomOut">缩小</a-button>
            <a-button type="primary" @click="toggleLinesAndText"
              >显示旗标</a-button
            >
            <a-button type="primary" @click="flipHorizontald"
              >水平翻转</a-button
            >
            <a-button type="primary" @click="flipVerticald">垂直翻转</a-button>
            <a-button type="primary" @click="rotate90">旋转90</a-button>

            <a-button type="primary" @click="rotateMinus90">旋转-90</a-button>
            <a-button type="primary" @click="reset">重置</a-button>
            <a-button type="primary" @click="goback">返回</a-button>
          </a-card>
        </div>
        <div>
          <a-card :style="{ width: '360px' }" title="解剖部位">
            <template #extra>
              <a-link></a-link>
            </template>
            <div> 暂无数据关联 </div>
          </a-card>
        </div>
      </div></div
    >
    <div class="lbox">
      <div
        v-for="item in imgsrc"
        :key="item.id"
        class="lboxitem"
        @click="tagdcom(item.id)"
      >
        <img :src="item.src" alt="" />
        <div class="msx" v-if="item.id == dcomid"></div>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
  import {
    defineComponent,
    reactive,
    ref,
    onMounted,
    onBeforeUnmount,
    SetupContext,
  } from 'vue';

  interface Marker {
    x: number;
    y: number;
    color: string;
    text?: string;
  }

  export default defineComponent({
    setup(props, { emit }: SetupContext) {
      const imgsrc = ref<{ id: number; src: string }[]>([
        { id: 1, src: './1.png' },
        { id: 2, src: './2.png' },
      ]);

      const state = reactive({
        canBiaoZhu: false,
        pointColor: 'red',
        pointSize: 10,
        imgScale: 1,
        zoomStep: 0.1,
        markers: [] as { dcomid: number; bsdata: Marker[] }[],
        canvas: null as HTMLCanvasElement | null,
        ctx: null as CanvasRenderingContext2D | null,
        img: new Image(),
        imgWidth: 1300,
        imgHeight: 500,
        currentText: '',
        currentMarker: null as Marker | null,
        showLinesAndText: true,
        isDragging: false,
        startDragX: 0,
        startDragY: 0,
        imgOffsetX: 0,
        imgOffsetY: 0,
        isSpacePressed: false,
        hoveredMarker: null as Marker | null,
        editingMarker: false,
        editPanelX: 0,
        editPanelY: 0,
        addflag: false,
        flipHorizontal: false,
        flipVertical: false,
        rotation: 0, // 0, 90, -90
      });
      const dcomid = ref(1);
      const goback = () => {
        emit('goback');
      };
      const flipHorizontald = () => {
        state.flipHorizontal = !state.flipHorizontal;
        draw();
      };

      const flipVerticald = () => {
        state.flipVertical = !state.flipVertical;
        draw();
      };

      const rotate90 = () => {
        state.rotation = (state.rotation + 90) % 360;
        draw();
      };

      const rotateMinus90 = () => {
        state.rotation = (state.rotation - 90 + 360) % 360;
        draw();
      };
      const checkHover = (x: number, y: number) => {
        const { markers, pointSize, imgScale, imgOffsetX, imgOffsetY } = state;
        const margin = 50; // Margin from the canvas edge

        // Find the current markers based on dcomid
        const targetElement = markers.find(
          (item) => item.dcomid === dcomid.value
        );
        if (targetElement) {
          state.hoveredMarker = targetElement.bsdata.find((marker) => {
            // 新方法计算新的偏移量
            const canvas = state.canvas!;
            const ctx = state.ctx!;

            // Clear the canvas
            ctx.clearRect(0, 0, canvas.width, canvas.height);

            // Calculate scaled image dimensions
            const scaledWidth = state.imgWidth * state.imgScale;
            const scaledHeight = state.imgHeight * state.imgScale;

            // Calculate image offset on the canvas
            const xOffset = (canvas.width - scaledWidth) / 2 + state.imgOffsetX;
            const yOffset =
              (canvas.height - scaledHeight) / 2 + state.imgOffsetY;

            const markerX = marker.x * state.imgScale + xOffset;
            const markerY = marker.y * state.imgScale + yOffset;
            // 新方法计算新的偏移量
            // Determine line end points
            let lineEndX =
              markerX < state.canvas!.width / 2
                ? margin
                : state.canvas!.width - margin;
            let lineEndY = markerY;

            // Check if hovering over the marker
            const isHoveringMarker =
              Math.hypot(x - markerX, y - markerY) < (pointSize / 2) * imgScale;
            if (isHoveringMarker) return true;

            // Check if hovering over the line
            const lineLength = Math.hypot(
              lineEndX - markerX,
              lineEndY - markerY
            );
            const distanceToLine =
              Math.abs(
                (lineEndY - markerY) * x -
                  (lineEndX - markerX) * y +
                  lineEndX * markerY -
                  lineEndY * markerX
              ) / lineLength;

            if (distanceToLine < 10 * imgScale) {
              // Check if hovering over the text
              const ctx = state.ctx!;
              const textWidth = ctx.measureText(marker.text || '').width;
              const textHeight = 14 * imgScale;
              const textPadding = -20 * imgScale; // Margin from the line

              let textX =
                markerX < state.canvas!.width / 2
                  ? lineEndX + textPadding
                  : lineEndX - textWidth - textPadding;
              let textY = lineEndY + textHeight / 2;

              return (
                x >= textX &&
                x <= textX + textWidth &&
                y >= textY - textHeight &&
                y <= textY
              );
            }

            return false;
          });
        }
      };
      // const checkHover = (x: number, y: number) => {
      //   console.log('点击了sss');

      //   const targetElement = state.markers.find(
      //     (item) => item.dcomid === dcomid.value
      //   );
      //   if (targetElement) {
      //     state.hoveredMarker = targetElement.bsdata.find((marker) => {
      //       // 新方法计算新的偏移量
      //       const canvas = state.canvas!;
      //       const ctx = state.ctx!;

      //       // Clear the canvas
      //       ctx.clearRect(0, 0, canvas.width, canvas.height);

      //       // Calculate scaled image dimensions
      //       const scaledWidth = state.imgWidth * state.imgScale;
      //       const scaledHeight = state.imgHeight * state.imgScale;

      //       // Calculate image offset on the canvas
      //       const xOffset = (canvas.width - scaledWidth) / 2 + state.imgOffsetX;
      //       const yOffset =
      //         (canvas.height - scaledHeight) / 2 + state.imgOffsetY;

      //       const markerX = marker.x * state.imgScale + xOffset;
      //       const markerY = marker.y * state.imgScale + yOffset;
      //       // 新方法计算新的偏移量
      //       const isHoveringMarker =
      //         Math.hypot(x - markerX, y - markerY) <
      //         (state.pointSize / 2) * state.imgScale;
      //       if (isHoveringMarker) return true;

      //       const isMarkerLeft =
      //         markerX < (state.canvas!.width - 50) / 2 + 50 / 2;
      //       const lineLength = 150 * state.imgScale;
      //       const lineEndX = isMarkerLeft
      //         ? markerX - lineLength
      //         : markerX + lineLength;
      //       const lineEndY = markerY;

      //       const distanceToLine =
      //         Math.abs(
      //           (lineEndY - markerY) * x -
      //             (lineEndX - markerX) * y +
      //             lineEndX * markerY -
      //             lineEndY * markerX
      //         ) / Math.hypot(lineEndY - markerY, lineEndX - markerX);

      //       if (distanceToLine < 10 * state.imgScale) {
      //         const textWidth = state.ctx!.measureText(marker.text || '').width;
      //         const textHeight = 14 * state.imgScale;
      //         const textPadding = 10 * state.imgScale;
      //         const textX =
      //           lineEndX +
      //           (isMarkerLeft ? -textWidth - textPadding : textPadding);
      //         const textY = lineEndY + 5 * state.imgScale;
      //         return (
      //           x >= textX &&
      //           x <= textX + textWidth &&
      //           y >= textY - textHeight &&
      //           y <= textY
      //         );
      //       }
      //       return false;
      //     });
      //   }
      // };

      const handleMouseMove = (e: MouseEvent) => {
        const canvasX = e.offsetX;
        const canvasY = e.offsetY;
        if (state.isDragging) {
          dragMove(e);
        } else {
          checkHover(canvasX, canvasY);
          draw();
        }
      };

      const handleCanvasClick = (e: MouseEvent) => {
        if (state.canBiaoZhu) {
          const canvasX = e.offsetX;
          const canvasY = e.offsetY;
          const imgX =
            (canvasX -
              (state.canvas!.width / 2 -
                (state.imgWidth * state.imgScale) / 2)) /
            state.imgScale;
          const imgY =
            (canvasY -
              (state.canvas!.height / 2 -
                (state.imgHeight * state.imgScale) / 2)) /
            state.imgScale;
          createMarker(imgX, imgY);
        } else if (state.hoveredMarker) {
          state.currentMarker = state.hoveredMarker;
          state.currentText = state.currentMarker.text || '';
        }
      };

      const createMarker = (x: number, y: number) => {
        if (state.canBiaoZhu) {
          state.addflag = true;
          state.currentMarker = { x, y, color: state.pointColor };
          draw();
        }
      };

      const zoomIn = () => {
        state.imgScale += state.zoomStep;
        draw();
      };

      const zoomOut = () => {
        if (state.imgScale > state.zoomStep) {
          state.imgScale -= state.zoomStep;
          draw();
        }
      };

      const draw = () => {
        const canvas = state.canvas!;
        const ctx = state.ctx!;
        const img = state.img;

        // Clear the canvas
        ctx.clearRect(0, 0, canvas.width, canvas.height);

        // Calculate scaled image dimensions
        const scaledWidth = state.imgWidth * state.imgScale;
        const scaledHeight = state.imgHeight * state.imgScale;

        // Calculate image offset on the canvas
        const xOffset = (canvas.width - scaledWidth) / 2 + state.imgOffsetX;
        const yOffset = (canvas.height - scaledHeight) / 2 + state.imgOffsetY;
        // console.log('偏移量', xOffset, yOffset);

        ctx.save();

        // Apply transformations
        ctx.translate(canvas.width / 2, canvas.height / 2); // Move to canvas center
        if (state.flipHorizontal) ctx.scale(-1, 1); // Flip horizontally
        if (state.flipVertical) ctx.scale(1, -1); // Flip vertically
        ctx.rotate((state.rotation * Math.PI) / 180); // Rotate
        ctx.translate(-canvas.width / 2, -canvas.height / 2); // Move back

        // Draw the image
        ctx.drawImage(img, xOffset, yOffset, scaledWidth, scaledHeight);

        // Restore context state for drawing markers
        ctx.restore();
        ctx.save();

        // Apply the same transformations to markers
        ctx.translate(canvas.width / 2, canvas.height / 2); // Move to canvas center
        if (state.flipHorizontal) ctx.scale(-1, 1); // Flip horizontally
        if (state.flipVertical) ctx.scale(1, -1); // Flip vertically
        ctx.rotate((state.rotation * Math.PI) / 180); // Rotate
        ctx.translate(-canvas.width / 2, -canvas.height / 2); // Move back
        // Define fixed margins and distances
        const margin = 70; // Margin from the canvas edge
        const textMargin = -40; // Margin between text and the line

        state.markers.forEach((item) => {
          if (item.dcomid === dcomid.value) {
            item.bsdata.forEach((marker) => {
              const markerX = marker.x * state.imgScale + xOffset;
              const markerY = marker.y * state.imgScale + yOffset;
              const isHovered = marker == state.hoveredMarker;
              // Draw marker point

              if (state.showLinesAndText) {
                ctx.fillStyle =
                  state.hoveredMarker === marker ? 'yellow' : marker.color;
                ctx.beginPath();
                ctx.arc(markerX, markerY, state.pointSize / 2, 0, 2 * Math.PI);
                ctx.fill();

                // Determine line end points
                let lineEndX =
                  markerX < canvas.width / 2 ? margin : canvas.width - margin;
                let lineEndY = markerY;

                // Draw line
                ctx.strokeStyle =
                  state.hoveredMarker === marker ? 'yellow' : marker.color;
                ctx.lineWidth = 1.5;
                ctx.beginPath();
                ctx.moveTo(markerX, markerY);
                ctx.lineTo(lineEndX, lineEndY);
                ctx.stroke();
                // Draw text
                ctx.fillStyle =
                  state.hoveredMarker === marker ? 'yellow' : 'green';
                ctx.font = `${14 * state.imgScale}px Arial`;

                const text = marker.text || '';
                const textWidth = ctx.measureText(text).width;
                const textHeight = 14 * state.imgScale;

                let textX = lineEndX;
                let textY = lineEndY + textHeight / 2;

                // Adjust text position
                textX =
                  markerX < canvas.width / 2
                    ? lineEndX + textMargin
                    : lineEndX - textWidth - textMargin;

                // Ensure text does not overlap with marker or line
                textX = Math.max(
                  textMargin,
                  Math.min(textX, canvas.width - textWidth - textMargin)
                );
                textY = Math.max(
                  textMargin + textHeight,
                  Math.min(textY, canvas.height - textMargin)
                );

                ctx.fillText(text, textX, textY);
              } else {
                console.log('走了我');

                // Draw new marker point without line and text
                // ctx.beginPath();
                ctx.fillStyle = isHovered ? 'yellow' : marker.color;
                ctx.moveTo(markerX, markerY);
                ctx.lineTo(markerX - 10, markerY - 20);
                ctx.lineTo(markerX + 10, markerY - 20);
                ctx.closePath();
                ctx.fill();
              }
            });
          }
        });

        if (
          state.currentMarker &&
          !state.editingMarker &&
          state.currentText === '' &&
          state.addflag
        ) {
          const { x, y } = state.currentMarker;
          const markerX = x * state.imgScale + xOffset;
          const markerY = y * state.imgScale + yOffset;

          if (state.showLinesAndText) {
            // Draw new marker point
            ctx.fillStyle = state.pointColor;
            ctx.beginPath();
            ctx.arc(markerX, markerY, state.pointSize / 2, 0, 2 * Math.PI);
            ctx.fill();

            // Determine line end points
            let lineEndX =
              markerX < canvas.width / 2 ? margin : canvas.width - margin;
            let lineEndY = markerY;

            // Draw line
            ctx.strokeStyle = state.pointColor;
            ctx.lineWidth = 1.5;
            ctx.beginPath();
            ctx.moveTo(markerX, markerY);
            ctx.lineTo(lineEndX, lineEndY);
            ctx.stroke();

            // Draw placeholder text
            ctx.fillStyle = 'red';
            ctx.font = `${12 * state.imgScale}px Arial`;
            const placeholderText = '请输入新建标记点';
            const placeholderTextWidth = ctx.measureText(placeholderText).width;
            const placeholderTextHeight = 12 * state.imgScale;

            let textX = lineEndX;
            let textY = lineEndY + placeholderTextHeight / 2;

            // Adjust text position
            textX =
              markerX < canvas.width / 2
                ? lineEndX + textMargin
                : lineEndX - placeholderTextWidth - textMargin;

            // Ensure text does not overlap with marker or line
            textX = Math.max(
              textMargin,
              Math.min(textX, canvas.width - placeholderTextWidth - textMargin)
            );
            textY = Math.max(
              textMargin + placeholderTextHeight,
              Math.min(textY, canvas.height - textMargin)
            );

            ctx.fillText(placeholderText, textX, textY);

            // Draw input box
            const inputBoxWidth = 120;
            const inputBoxHeight = 20;
            const inputBoxPadding = 5;

            let inputBoxX = textX;
            let inputBoxY = textY + placeholderTextHeight;

            // Adjust input box position
            inputBoxX =
              markerX < canvas.width / 2 ? textX : textX - inputBoxWidth;

            ctx.fillStyle = 'white';
            ctx.strokeStyle = 'black';
            ctx.lineWidth = 1;

            // Draw input box
            ctx.beginPath();
            ctx.rect(inputBoxX, inputBoxY, inputBoxWidth, inputBoxHeight);
            ctx.stroke();
            ctx.fill();

            // Draw input box text (if any)
            ctx.fillStyle = 'black';
            ctx.font = `${12 * state.imgScale}px Arial`;
            ctx.fillText(
              state.currentText || placeholderText,
              inputBoxX + inputBoxPadding,
              inputBoxY + inputBoxHeight / 2 + 5
            );
          } else {
            // Draw new marker point without line and text
            ctx.fillStyle = state.pointColor;
            ctx.beginPath();
            ctx.moveTo(markerX, markerY);
            ctx.lineTo(markerX - 10, markerY - 20);
            ctx.lineTo(markerX + 10, markerY - 20);
            ctx.closePath();
            ctx.fill();
          }
        }
        // Restore context state
        ctx.restore();
      };

      const loadMarkers = () => {
        const cachedMarkers = localStorage.getItem('markers');
        if (cachedMarkers) {
          state.markers = JSON.parse(cachedMarkers);
          draw();
        }
      };

      const toggleLinesAndText = () => {
        state.showLinesAndText = !state.showLinesAndText;
        draw();
      };

      const startDrag = (e: MouseEvent) => {
        if (state.isSpacePressed && e.button === 0) {
          state.isDragging = true;
          const rect = state.canvas!.getBoundingClientRect();
          state.startDragX = e.clientX - rect.left - state.imgOffsetX;
          state.startDragY = e.clientY - rect.top - state.imgOffsetY;
          e.preventDefault();
        }
      };

      const stopDrag = () => {
        state.isDragging = false;
      };

      const dragMove = (e: MouseEvent) => {
        if (state.isDragging) {
          const rect = state.canvas!.getBoundingClientRect();
          state.imgOffsetX = e.clientX - rect.left - state.startDragX;
          state.imgOffsetY = e.clientY - rect.top - state.startDragY;
          draw();
        }
      };

      const handleKeyDown = (e: KeyboardEvent) => {
        if (e.code === 'Space') {
          state.isSpacePressed = true;
        }
      };

      const handleKeyUp = (e: KeyboardEvent) => {
        if (e.code === 'Space') {
          state.isSpacePressed = false;
        }
      };

      const tagdcom = (i: number) => {
        dcomid.value = i;
        state.img.src = imgsrc.value[i - 1].src;
        draw();
      };

      const handleWheel = (e: WheelEvent) => {
        e.preventDefault();
        if (e.deltaY < 0 && dcomid.value > 1) {
          dcomid.value -= 1;
          tagdcom(dcomid.value);
          draw();
        } else if (e.deltaY > 0 && dcomid.value < imgsrc.value.length) {
          dcomid.value += 1;
          tagdcom(dcomid.value);
          draw();
        }
      };

      onMounted(() => {
        state.canvas = document.getElementById('myCanvas') as HTMLCanvasElement;
        state.ctx = state.canvas.getContext('2d');
        state.img.src = imgsrc.value[0].src;
        state.img.onload = () => {
          loadMarkers();
          draw();
        };

        state.canvas.addEventListener('mousedown', startDrag);
        state.canvas.addEventListener('mousemove', handleMouseMove);
        state.canvas.addEventListener('mouseup', stopDrag);
        state.canvas.addEventListener('click', handleCanvasClick);
        state.canvas.addEventListener('wheel', handleWheel);
        document.addEventListener('keydown', handleKeyDown);
        document.addEventListener('keyup', handleKeyUp);
      });

      onBeforeUnmount(() => {
        if (state.canvas) {
          state.canvas.removeEventListener('mousedown', startDrag);
          state.canvas.removeEventListener('mousemove', handleMouseMove);
          state.canvas.removeEventListener('mouseup', stopDrag);
          state.canvas.removeEventListener('click', handleCanvasClick);
          state.canvas.removeEventListener('wheel', handleWheel);
        }
        document.removeEventListener('keydown', handleKeyDown);
        document.removeEventListener('keyup', handleKeyUp);
      });
      const reset = () => {
        // 重置状态
        state.imgScale = 1;
        state.zoomStep = 0.1;
        state.rotation = 0;
        state.flipHorizontal = false;
        state.flipVertical = false;
        state.imgOffsetX = 0;
        state.imgOffsetY = 0;
        state.currentText = '';
        state.currentMarker = null;
        state.addflag = false;
        state.showLinesAndText = true;

        // 重新加载并绘制图像
        state.img.src = imgsrc.value[dcomid.value - 1].src;
        state.img.onload = () => {
          loadMarkers();
          draw();
        };
      };

      return {
        reset,
        imgsrc,
        state,
        flipHorizontald,
        flipVerticald,
        rotate90,
        rotateMinus90,
        zoomIn,
        zoomOut,
        toggleLinesAndText,
        tagdcom,
        dcomid,
        goback,
      };
    },
  });
</script>

<style scoped>
  .mainboxgj {
    display: flex;
    width: 100%;
  }
  .bocd .arco-btn {
    margin: 5px 10px;
  }
  #myCanvas {
    /* border: solid 1px #00ff80; */
    background-color: black;
  }

  .boxs {
    width: 300px;
    display: flex;
    flex-direction: column;
    align-content: center;
    justify-content: center;
  }
  .boxsitem {
    width: 130px;
    height: 130px;
    margin: 10px 25px;
    background: black;
  }
  .boxsitems {
    text-align: center;
  }
  .box {
    margin: 10px auto;
    /* background-color: #00ff80; */
    width: 1300px;
  }

  .bocd {
    margin: 10px;
    display: flex;
    flex-direction: column;
  }

  .lbox {
    width: 1440px;
    height: 100px;
    display: flex;
    margin: 0 auto;
  }

  .lboxitem {
    width: 100px;
    height: 100px;
    cursor: pointer;
    position: relative;
  }

  .lboxitem img {
    width: 100px;
    height: 100px;
  }

  .msx {
    height: 100px;
    width: 2px;
    background-color: blue;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }
</style>
